
// draws a single graph
// uses plenv

#include <Python.h>
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include <numpy/arrayobject.h>
#include <plplot/plplot.h>

#include <stdio.h>
#include <stdbool.h>
#include <string.h>

void plot_data (PyObject* stonk_datum, const char *ticker) {
    // prepare to plot
    int nd = PyArray_NDIM(
        (PyArrayObject *)stonk_datum
    );
    npy_intp *dims = PyArray_DIMS(
        (PyArrayObject *)stonk_datum
    );
    unsigned int rows = dims[0];
    double *x = (double*) malloc (rows * sizeof(double));
    double *y = (double*) malloc (rows * sizeof(double));
    #define TIMESTAMP_COL 0
    #define CLOSE_PRICE_COL 3
    //  time,   open,   high,   low,    close,  volume
    //  0       1       2       3       4       5
    double time, close, high, low;
    double ymax =  0;
    double ymin = -1;
    for (npy_intp i = 0; i < rows ; i++) {
        // just copy the tiem for x axis
        time = *(double *)PyArray_GETPTR2(
                (PyArrayObject *)stonk_datum, i, 0);
        x[i] = time;
        close = *(double *)PyArray_GETPTR2(
                (PyArrayObject *)stonk_datum, i, 4);
        y[i] = close;
        high = *(double *)PyArray_GETPTR2(
                (PyArrayObject *)stonk_datum, i, 2);
        if (high > ymax) {
            ymax = high;
        }
        low = *(double *)PyArray_GETPTR2(
                (PyArrayObject *)stonk_datum, i, 3);
        if (low < ymin || ymin == -1) {
            ymin = low;
        }
    }
    // printf("*(%.2f, %.2f)\n", ymin, ymax);
    double xmin = x[0];
    double xmax = x[rows-1];
    char title[256];
    strcat(title, ticker);
    plinit();
    plenv( xmin, xmax, ymin, ymax, 0, 0 );
    pllab( "x in unix time", "Price (USD)", title);
    plline(rows, x, y );

    plend();
    free(x);
    free(y);
}

void get_user_input(char *input) {
    printf("Enter a ticker: ");
    if (fgets(input, sizeof(input), stdin) != NULL) {
        input[strcspn(input, "\n")] = '\0'; 

    } else {
          perror("Error reading input");
    }
    size_t len = strlen(input);
    // turn to caps for aesthetics.
    for (unsigned int i=0; i < len; i++) {
        input[i] = toupper(input[i]);
    }
    return;
}

bool get_numpy_array(PyObject *script) {
    if (script == NULL) {
        return false;
    }
    bool is_ok = true;
    PyObject *pyfn = PyObject_GetAttrString(script, "invoke_from_c");
    if (pyfn == NULL || !PyCallable_Check(pyfn)) {
        if (PyErr_Occurred()) {
            PyErr_Print();
        }
        is_ok = false;
        goto free;
    }
    char s[16];
    get_user_input(s);
    PyObject *pargs = PyTuple_Pack(
        1, PyUnicode_FromString(s)
    ); 
    PyObject *numpy_array = PyObject_CallObject(pyfn, pargs);
    Py_XDECREF(pargs);
    if (numpy_array == NULL) {
        if (PyErr_Occurred()) {
            PyErr_Print();
        }
        fprintf(stderr, "Call to invoke_from_c() failed\n");
        is_ok = false;
        goto free;
    }
    if (!PyArray_Check(numpy_array)) {
        fprintf(stderr, "did not get a numpy array from function");
        is_ok = false;
        goto free;
    }
    // Get the dimensions of the array
    int nd = PyArray_NDIM((PyArrayObject *)numpy_array);
    npy_intp *dims = PyArray_DIMS(
        (PyArrayObject *)numpy_array
    );
    printf("Array dimensions: %d x %d\n", dims[0], dims[1]);
    // Access the elements of the 2D array
    #define PREVIEW_ROWS_MAX 3
    #define PREVIEW_COLS_MAX 5
    for (npy_intp i = 0; i < PREVIEW_ROWS_MAX; i++) {
        for (npy_intp j = 0; j < PREVIEW_COLS_MAX; j++) {
            // Get the value at (i, j)
            double value = *(double *)PyArray_GETPTR2(
                (PyArrayObject *)numpy_array, i, j);
            
            printf("%.2lf, ", i, j, value);
        }
        printf("\n");
    }
    plot_data(numpy_array, s);
    free:
    if (pyfn) {
        Py_XDECREF(pyfn);
    }
    if (numpy_array) {
        Py_XDECREF(numpy_array);
    }
    return is_ok;
}

int main() {
    // Initialize the Python Interpreter
    Py_Initialize();
    // import_array(); // Necessary for NumPy
    import_array1(0);  // same but less compiler complaints
    // Import the Python module
    PyObject *pName = PyUnicode_FromString("demo1_get-price"); // Name of your Python script without .py
    PyObject *pModule = PyImport_Import(pName);
    if (pModule == NULL) {
        PyErr_Print();
        fprintf(stderr, "Failed to load 'demo1'\n");
        goto end;
    }
    bool success = get_numpy_array(pModule);
    end:
    if (pModule) {
        Py_DECREF(pModule);
    }
    if (pName) {
        Py_DECREF(pName);
    }
    // Finalize the Python Interpreter
    Py_Finalize();
    return 0;
}



